<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>checkbox test</title>

<script type="text/javascript" src="../jslib/jquery-1.10.2.js"></script>
<style type="text/css">
.base {
	list-style: none;
	border: 1px solid #000;
	width: 30em;
	margin-left: 2em;
	margin-top: 0px;
	padding-left: 5px;
}

.base li{
	margin-top: 1px;
}
.x7,.zE{
    background-attachment: scroll;
    background-clip: border-box;
    background-image: none;
    background-origin: padding-box;
    background-position: 0 0;
    background-repeat: repeat;
    background-size: auto auto;
}
.x7 {
    background-color: #FFFFCC;   /*yellow color*/
    color: #222222;
}
.zE {
    background-color: #FFFFFF;
    color: #000000;
}

span.all{
	margin-left: 2em;
}
</style>
<script>
	$(document).ready(function (){ 
		new op.addBoxListener();
		new op.addKeyListener();
		new op.selectAll();
		new op.reverseSelect();
		//new op.checkboxScopeSelect();
	}); 
	
	var op = {
		shiftKey : '',
		selectAllFlag : false,
		addBoxListener : function(){
			//$(':checkbox') is equivalent to $('[type=checkbox]'). 
			var boxs = $(':checkbox[name="item"]');
			boxs.click(
				function(){
					//alert(op.shiftKey);
					if(op.shiftKey){
						new op.debugInfo('shift key down ' + "  checkbox id is " + this.id);
						//alert(this)
						var currId = parseInt(this.id);
						var nextDownId = currId + 1;
						var flag = 0;
						while(true){
							var nextDownItem = $('#' + nextDownId);
							if(nextDownItem.length == 0){
								break;
							}
							if(nextDownItem[0].checked){
								flag = 1;    //向后遍历，如果有被选中的checkbox,flag 置1;
								break;
							}
							nextDownId++;
						}
						
						if(!flag){
							var prevDownItemId = currId -1;
							while(true){
								var prevDownItem = $('#' + prevDownItemId);
								if(prevDownItem.length == 0){
									break;
								}
								if(prevDownItem[0].checked){
									flag = 2;   ////向前遍历，如果有被选中的checkbox,flag 置2;
									break;
								}
								prevDownItemId--;
							}
						}
						
						var index = 0;
						var initVal = 0;
						switch(flag){
							case 0:
								break;
							case 1:
								index = nextDownId;
								initVal = currId;
								for(var i = initVal; i <= index; i++){
									var item = $('#' + i);
									item.attr("checked",true);
									$(item[0].parentNode).removeClass('zE').addClass('x7');
								}
								break;
							case 2:
								index = prevDownItemId;
								initVal = currId;
								for(var i = initVal; i >= index; i--){
									var item = $('#' + i);
							    	item.attr("checked",true);
							    	$(item[0].parentNode).removeClass('zE').addClass('x7');
								}
								break;
								
						}
					}else{
						new op.debugInfo('not have shift key' + "  checkbox id is " + this.id);
						var isCheched = this.checked;
						if(isCheched){
							this.checked = true;
							$(this.parentNode).removeClass('zE').addClass('x7');
						}else{
							this.checked = false;
							$(this.parentNode).removeClass('x7').addClass('zE');
						}
					}
				}
			); 			
		},
		select : function(checkbox){
	    	var obj = checkbox.parentNode;
	    	var objName = obj.nodeName;
	    	if(objName == 'LI'){
		    	$(checkbox).attr("checked", op.selectAllFlag);
		    	
		    	$(obj).removeClass(!op.selectAllFlag ? 'x7' : 'zE')
		    		  .addClass(op.selectAllFlag ? 'x7' : 'zE');
	    	}			
		},
		selectAll : function(){
			var itemAll = $('#itemAll');
			itemAll.click(
				function(){
					op.selectAllFlag = !op.selectAllFlag;
					itemAll[0].checked = op.selectAllFlag;
					
				    $("input[type='checkbox']").each(function() {
				    	new op.select(this);
				  	})					
				}
			);
			
		},
		addKeyListener : function(){
			$(document).keydown(function(event){
				//16 = Shift_L
				if(event.keyCode == 16){
					//new op.debugInfo('keydown-->' + event.keyCode);
					op.shiftKey = true;
				}
			});
			
			$(document).keyup(function(event){
				if(event.keyCode == 16){
					new op.debugInfo('keyup-->' + event.keyCode);
				}
				op.shiftKey = false;
			}); 			
		},
		checkboxScopeSelect : function(){
			var dx,dy,ux,uy;
			
			$(document).mousedown(function(event){
				dx =event.clientX;
				dy = event.clientY
			});
			
			$(document).mouseup(function(event){
				ux = event.clientX;
				uy = event.clientY;
				
				if(ux - dx < 20 || uy - dy < 20)return;
								
				$("input[type='checkbox']").each(function() {
					var ltX = new elememtXY.x(this).x;
					var ltY = new elememtXY.y(this).y;
					var rdX = ltX + this.clientWidth;
					var rdY = ltY + this.clientHeight;
					
					if(ltX >= dx && ltY >= dy && rdX <= ux && rdY <= uy){
						new op.select(this);
					}
				});
				
			});			
		},		
		debugInfo : function(text){
			var ul = $('#info')[0];
			var date = new Date();
			//new Date().toLocaleString()->2011年6月14日 17:12:50
			var formatDate = date.toTimeString();
			
			var info = formatDate + ":" + text;
			$("<li/>").css("border","solid 1px #FF0000").html(info).appendTo(ul);
		},
		reverseSelect : function(){
			$('#reverse').click(function(event){
				$("input[type='checkbox']").each(
					function() {
					switch(this.name){
						case 'itemAll' :
						break;
						case 'reverse' :
						break;
						default :{
							this.checked = !this.checked;
							var parentNode = this.parentNode;
							if(parentNode.className == 'x7'){
								parentNode.className = 'zE';
							}else if(parentNode.className == 'zE'){
								parentNode.className = 'x7';
							}
						}
					}
				}
				);	
			});
		}
	};
	
	var elememtXY = {
		x : function(e){
			return {x : getLeft(e)};
		},
		y : function(e){
			return {y : getTop(e)};
		}
	}
	
	function getTop(e) {
		var offset = e.offsetTop;
		while((e = e.offsetParent) != null){
			offset += e.offsetTop;
		}
		return offset;
	}
	
	function getLeft(e) {
		var offset = e.offsetLeft;
		while((e = e.offsetParent) != null) {
			offset += e.offsetLeft;
		}
		return offset;
	}	

</script>
</head>
<body>
	<div>
		<span class="all"><input id="itemAll" type="checkbox" name="itemAll"/>全选</span>
		<span><input id="reverse" type="checkbox" name="reverse"></input>反选</span>
	</div>
	<ul id='ul' class="base">
		<li><input id="1" type="checkbox" name="item"/></li>
		<li><input id="2" type="checkbox" name="item"/></li>
		<li><input id="3" type="checkbox" name="item"/></li>
		<li><input id="4" type="checkbox" name="item"/></li>
		<li><input id="5" type="checkbox" name="item"/></li>
		<li><input id="6" type="checkbox" name="item"/></li>
		<li><input id="7" type="checkbox" name="item"/></li>
		<li><input id="8" type="checkbox" name="item"/></li>
		<li><input id="9" type="checkbox" name="item"/></li>
		<li><input id="10" type="checkbox" name="item"/></li>
		<li><input id="11" type="checkbox" name="item"/></li>
		<li><input id="12" type="checkbox" name="item"/></li>
		<li><input id="13" type="checkbox" name="item"/></li>
		<li><input id="14"  type="checkbox" name="item"/></li>
	</ul>
	<ul id='info' class="base"></ul>
</body>
</html>